package com.e1xp.deport_management_system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.e1xp.deport_management_system.entity.ProductRack;
import com.e1xp.deport_management_system.entity.Rack;
import com.e1xp.deport_management_system.exception.CustomException;
import com.e1xp.deport_management_system.exception.CustomExceptionType;
import com.e1xp.deport_management_system.mapper.ProductRackMapper;
import com.e1xp.deport_management_system.mapper.RackMapper;
import com.e1xp.deport_management_system.service.IRackService;
import com.e1xp.deport_management_system.service.IUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author E1xP
 * @since 2021-04-09
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class RackServiceImpl extends ServiceImpl<RackMapper, Rack> implements IRackService {

    @Resource
    RackMapper rackMapper;

    @Resource
    IUserService userService;

    @Resource
    ProductRackMapper productRackMapper;

    /**
     * 返还系统中架子数量
     *
     * @param instanceId 实例id
     * @return 架子数量
     */
    @Override
    public long getCount(long instanceId) {
        QueryWrapper<Rack> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("instance_id", instanceId);
        return rackMapper.selectCount(queryWrapper);
    }

    /**
     * 返还系统中所有货架信息
     *
     * @param instanceId 实例id
     * @return List Rack货架信息
     */
    @Override
    public List<Rack> getList(long instanceId) {
        QueryWrapper<Rack> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("instance_id", instanceId);
        return rackMapper.selectList(queryWrapper);
    }

    /**
     * 用于检查是否已有同名货架
     *
     * @param instanceId 实例id
     * @param rackName   货架名
     * @return 是否存在同名或货架
     */
    @Override
    public boolean isRack(long instanceId, String rackName) {
        QueryWrapper<Rack> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("instance_id", instanceId)
                .eq("name", rackName);
        return rackMapper.selectCount(queryWrapper) > 0;
    }

    /**
     * 用于检查货架是否存在
     *
     * @param instanceId 实例id
     * @param rackId     货架id
     * @return 是否存在同名或货架
     */
    @Override
    public boolean isRack(long instanceId, long rackId) {
        QueryWrapper<Rack> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("instance_id", instanceId)
                .eq("id", rackId);
        return rackMapper.selectCount(queryWrapper) > 0;
    }

    /**
     * 用于添加货架
     *
     * @param instanceId 实例id
     * @param rack       货架实体
     * @throws CustomException 当实例不存在、已存在同名货架、传入数据不完整时抛出该异常
     */
    @Override
    public void add(long instanceId, Rack rack) throws CustomException {
        if (!userService.isInstance(instanceId)) {
            //实例不存在
            throw new CustomException(CustomExceptionType.INSTANCE_NOT_FOUND_ERROR, "找不到指定实例");
        }
        if (isRack(instanceId, rack.getName())) {
            //已存在同名货架
            throw new CustomException(CustomExceptionType.RACK_HAD_BEEN_ADD, "已存在同名货架");
        }
        if (rack.getName() == null || rack.getName().isEmpty()) {
            //传入数据不完整
            throw new CustomException(CustomExceptionType.USER_INPUT_ERROR, "货架数据不完整");
        }
        rack.setInstanceId(instanceId);
        rackMapper.insert(rack);
    }

    /**
     * 用于更新货架信息
     *
     * @param instanceId 实例id
     * @param rack       货架实体类
     * @throws CustomException 当实例不存在，传入数据不完整时抛出该异常
     */
    @Override
    public void update(long instanceId, Rack rack) throws CustomException {
        if (!userService.isInstance(instanceId)) {
            //实例不存在
            throw new CustomException(CustomExceptionType.INSTANCE_NOT_FOUND_ERROR, "找不到该实例");
        }
        if (rack.getId() == null ||
                rack.getName() == null || rack.getName().isEmpty()) {
            //传入数据不完整
            throw new CustomException(CustomExceptionType.USER_INPUT_ERROR, "传入货架数据不完整");
        }
        rackMapper.updateById(rack);
    }

    /**
     * 用于检查货架上是否有商品
     *
     * @param instanceId 实例id
     * @param rackId     货架id
     * @return 货架上是否有商品
     */
    public boolean hasProduct(long instanceId, long rackId) {
        QueryWrapper<ProductRack> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("instance_id", instanceId)
                .eq("rack_id", rackId);
        return productRackMapper.selectCount(queryWrapper) > 0;
    }

    /**
     * 删除货架
     *
     * @param instanceId 实例id
     * @param rackId     货架id
     * @throws CustomException 当实例不存在，货架不存在，货架不为空时抛出该异常
     */
    @Override
    public void delete(long instanceId, long rackId) throws CustomException {
        if (!userService.isInstance(instanceId)) {
            //实例不存在
            throw new CustomException(CustomExceptionType.INSTANCE_NOT_FOUND_ERROR, "找不到该实例");
        }
        if (!isRack(instanceId, rackId)) {
            //货架不存在
            throw new CustomException(CustomExceptionType.RACK_NOT_FOUND_ERROR, "找不到该货架");
        }
        if (this.hasProduct(instanceId, rackId)) {
            //若货架上仍有商品
            throw new CustomException(CustomExceptionType.RACK_NOT_FOUND_ERROR, "货架不为空");
        }
        rackMapper.deleteById(rackId);
    }

    /**
     * 查询货架实体类
     *
     * @param instanceId 实例id
     * @param rackId     货架id
     * @return Rack实体
     */
    @Override
    public Rack get(long instanceId, long rackId) {
        QueryWrapper<Rack> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("instance_id", instanceId)
                .eq("id", rackId);
        return rackMapper.selectOne(queryWrapper);
    }

    /**
     * 用于获取货架信息
     *
     * @param instanceId instanceId
     * @return List Map货架信息
     */
    @Override
    public List<Map<String, String>> getSelection(long instanceId) {
        return rackMapper.getSelect(instanceId);
    }
}
